import { checkType, getType } from './StringUtil';

const assginValue = (
  key: string,
  value: any,
  container: GObject,
  callback: (obj: object, val: any) => void,
) => {
  const cTypeIsObj = checkType('Object', container[key]);
  const vTypeIsObj = checkType('Object', value);

  if (cTypeIsObj && vTypeIsObj) {
    container[key] = callback(container[key], value);
  } else if (vTypeIsObj) {
    container[key] = callback({}, value);
  } else {
    container[key] = value;
  }

  return container;
};

/**
 * 简单对象的深拷贝
 * @param {Array<Any>} args 参数列表
 * @return {Object<Any>}
 */
export const simpleCopy = (...args: any) => {
  let res = {};

  args.forEach((source: any) => {
    for (const key in source) {
      res = assginValue(key, source[key], res, simpleCopy);
    }
  });

  return res;
};

export function simpleExtends(...args: any) {
  const extendsFn =
    Object.assign ??
    function (target: GObject) {
      for (let i = 1; i < args.length; i++) {
        const source: GObject = args[i];

        for (let key in source) {
          if (Object.prototype.hasOwnProperty.call(source, key)) {
            target[key] = source[key];
          }
        }
      }

      return target;
    };

  return extendsFn(args);
}

export const deepcopy = <T>(target: T): T => {
  if (target === null) {
    return target;
  }
  if (target instanceof Date) {
    return new Date(target.getTime()) as any;
  }
  if (target instanceof Array) {
    const cp = [] as any[];
    (target as any[]).forEach((v) => {
      cp.push(v);
    });
    return cp.map((n: any) => deepcopy<any>(n)) as any;
  }
  if (typeof target === 'object') {
    const cp = { ...(target as { [key: string]: any }) } as {
      [key: string]: any;
    };
    Object.keys(cp).forEach((k) => {
      cp[k] = deepcopy<any>(cp[k]);
    });
    return cp as T;
  }
  return target;
};

export const deepClone = (data: any): any => {
  // 获取传入拷贝函数的数据类型
  const type = getType(data);
  // 定义一个返回any类型的数据
  let reData: any;
  // 递归遍历一个array类型数据，
  if (type === 'array') {
    reData = [];
    for (let i = 0; i < data.length; i++) {
      reData.push(deepClone(data[i]));
    }
  } else if (type === 'object') {
    //递归遍历一个object类型数据
    reData = {};
    for (const i in data) {
      reData[i] = deepClone(data[i]);
    }
  } else {
    // 返回基本数据类型
    return data;
  }
  // 将any类型的数据return出去，作为deepClone的结果
  return reData;
};

/**
 * 对象深拷贝
 * @param source
 * @returns
 */
export const deepClone2 = <T>(
  source: T,
  target?: Record<string, any> | T,
  isSimple?: boolean,
): T => {
  if (getType(source) === 'array') {
    target = target || [];
  } else {
    target = target || {};
  }
  for (const key in source) {
    if (Object.prototype.hasOwnProperty.call(source, key)) {
      // 对象浅拷贝
      target[key] = source[key];
      if (
        typeof source[key] === 'object' &&
        typeof source[key] !== null &&
        !isSimple
      ) {
        // 对象深拷贝
        target[key] = getType(source[key]) === 'array' ? [] : {};
        deepClone2(source[key], target[key], isSimple);
      }
    }
  }
  return target as T;
};
